package com.jrx.anytxn.transaction.service.impl;

import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.entity.TlMarketingRecord;
import com.jrx.anytxn.param.entity.PrCodeTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.service.system.ICodeTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.service.IMarketingFileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

@Service
public class MarketingFileServiceImpl implements IMarketingFileService {

    private static final Logger logger = LoggerFactory.getLogger(MarketingFileServiceImpl.class);
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Autowired
    private ICodeTableService codeTableService;

    @Override
    public void mergeFile(PrOrganizationTable org, String filePath, String fileName, String fileType) throws IOException{
        logger.info("开始合并分库文件。。。");
        Date bussinessDate = org.getToday();
        String toDay = DateUtils.format(bussinessDate,"yyyyMMdd");
        String reportingPath = filePath + org.getTenantId() + File.separator + toDay + File.separator;

        //生成营销文件
        mergeReportingFile(reportingPath, toDay, fileType, org.getTenantId());
        logger.info("合并分库文件结束。。。");
    }

    @Override
    public String createMarketingDetialFileMessage(TlMarketingRecord record) {
        String liveProvince = ""; //居住地址：省
        String liveCity = "";     //居住地址：市
        String liveArea = "";     //居住地址：区
        String workProvince = ""; //工作地址：省
        String workCity = "";     //工作地址：市
        String workArea = "";     //工作地址：区
        String workType = "";     //职业类型
        BigDecimal creditRest = BigDecimal.ZERO; //剩余可用额度

        if(StringUtils.isNotBlank(record.getLiveProvince())){
            PrCodeTable province = codeTableService.findByTypeAndCodeId(TransBizConstant.PROVINCE_TYPE_ID,
                    record.getLiveProvince(), record.getTenantId());
            if(null != province){
                liveProvince = province.getCodeName();
            }
        }
        if(StringUtils.isNotBlank(record.getLiveCity())){
            PrCodeTable city = codeTableService.findByTypeAndCodeId(TransBizConstant.CITY_TYPE_ID,
                    record.getLiveCity(), record.getTenantId());
            if(null != city){
                liveCity = city.getCodeName();
            }
        }
        if(StringUtils.isNotBlank(record.getLiveArea())){
            PrCodeTable area = codeTableService.findByTypeAndCodeId(TransBizConstant.AREA_TYPE_ID,
                    record.getLiveArea(), record.getTenantId());
            if(null != area){
                liveArea = area.getCodeName();
            }
        }
        if(StringUtils.isNotBlank(record.getWorkProvince())){
            PrCodeTable province = codeTableService.findByTypeAndCodeId(TransBizConstant.PROVINCE_TYPE_ID,
                    record.getWorkProvince(), record.getTenantId());
            if(null != province){
                workProvince = province.getCodeName();
            }
        }
        if(StringUtils.isNotBlank(record.getWorkCity())){
            PrCodeTable city = codeTableService.findByTypeAndCodeId(TransBizConstant.CITY_TYPE_ID,
                    record.getWorkCity(), record.getTenantId());
            if(null != city){
                workCity = city.getCodeName();
            }
        }
        if(StringUtils.isNotBlank(record.getWorkArea())){
            PrCodeTable area = codeTableService.findByTypeAndCodeId(TransBizConstant.AREA_TYPE_ID,
                    record.getWorkArea(), record.getTenantId());
            if(null != area){
                workArea = area.getCodeName();
            }
        }
        if(StringUtils.isNotBlank(record.getWorkType())){
            PrCodeTable work = codeTableService.findByTypeAndCodeId(TransBizConstant.INDUSTRY_TYPE_ID,
                    record.getWorkType(), record.getTenantId());
            if(null != work){
                workType = work.getCodeName();
            }
        }
        //授信阶段，剩余可用额度等于授信金额
        if(CustomerConstant.MARKET_STEP_2.equals(record.getStep()) && null != record.getCreditAmount()){
            creditRest = record.getCreditAmount();
        }
        StringBuffer sb = new StringBuffer();
        sb.append("\""+(record.getSeqNo()==null?"":record.getSeqNo()) + "\""+ TransBizConstant.SPLIT); //流水号
        sb.append("\""+(record.getRecommenderCode()==null?"":record.getRecommenderCode()) + "\""+ TransBizConstant.SPLIT); //推荐人编码
        sb.append("\""+(record.getTenantId()==null?"":record.getTenantId()) + "\""+ TransBizConstant.SPLIT); //租户ID
        sb.append("\""+(record.getUserId()==null?"":record.getUserId()) + "\""+ TransBizConstant.SPLIT); //用户user_id
        sb.append("\""+(record.getIdNumber()==null?"":record.getIdNumber()) + "\""+ TransBizConstant.SPLIT); //证件号码
        sb.append("\""+(record.getMobile()==null?"":record.getMobile()) + "\""+ TransBizConstant.SPLIT); //手机号
        sb.append("\""+(record.getChineseName()==null?"":record.getChineseName()) + "\""+ TransBizConstant.SPLIT); //中文名称
        sb.append("\""+(record.getStep()==null?"":record.getStep()) + "\""+ TransBizConstant.SPLIT); //所属阶段： 1-注册 2-授信 3-借款
        sb.append("\""+(record.getCreditAmount()==null?"0.00":record.getCreditAmount().setScale(2, BigDecimal.ROUND_HALF_UP)) + "\""+ TransBizConstant.SPLIT); //授信金额
        sb.append("\""+(record.getLoanAmount()==null?"0.00":record.getLoanAmount().setScale(2, BigDecimal.ROUND_HALF_UP)) + "\""+ TransBizConstant.SPLIT); //借款金额
        sb.append("\""+ creditRest.setScale(2, BigDecimal.ROUND_HALF_UP) + "\""+ TransBizConstant.SPLIT); //剩余可用额度
        sb.append("\""+(BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP)) + "\""+ TransBizConstant.SPLIT); //待还款总额
        sb.append("\""+(BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP)) + "\""+ TransBizConstant.SPLIT); //逾期总额
        sb.append("\""+(BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP)) + "\""+ TransBizConstant.SPLIT); //非应计金额
        sb.append("\""+ liveProvince + "\""+ TransBizConstant.SPLIT); //居住地址：省
        sb.append("\""+ liveCity + "\""+ TransBizConstant.SPLIT); //居住地址：市
        sb.append("\""+ liveArea + "\""+ TransBizConstant.SPLIT); //居住地址：区
        sb.append("\""+(record.getLiveAddress()==null?"":record.getLiveAddress()) + "\""+ TransBizConstant.SPLIT); //详细居住地址
        sb.append("\""+ workProvince + "\""+ TransBizConstant.SPLIT); //工作地址：省
        sb.append("\""+ workCity + "\""+ TransBizConstant.SPLIT); //工作地址：市
        sb.append("\""+ workArea + "\""+ TransBizConstant.SPLIT); //工作地址：区
        sb.append("\""+(record.getWorkAddress()==null?"":record.getWorkAddress()) + "\""+ TransBizConstant.SPLIT); //详细工作地址
        sb.append("\""+ workType + "\""+ TransBizConstant.SPLIT); //职业类别
        sb.append("\""+(record.getCompanyName()==null?"":record.getCompanyName()) + "\""+ TransBizConstant.SPLIT); //公司名称
        sb.append("\""+DateUtils.format(record.getBusinessDate(), DateUtils.DATE_PATTERN_ANOTHER) + "\""+ TransBizConstant.SPLIT); //业务日期 yyyyMMdd
        sb.append("\""+DateUtils.format(record.getBusinessTime(), DateUtils.TIME_PATTERN_ANOTHER) + "\""+ TransBizConstant.SPLIT); //交易时间 HHmmss
        sb.append("\""+"" + "\""+ TransBizConstant.SPLIT); //openId
        sb.append("\""+"" + "\""+ TransBizConstant.SPLIT); //头像链接
        sb.append("\""+(record.getChineseName()==null?"":record.getChineseName()) + "\""+ TransBizConstant.SPLIT); //昵称
        sb.append("\""+"" + "\""); //分享人编号
        return sb.toString();
    }

    @Override
    public void generatingFile(List<String> messageList, String reportingPath, String fileName, String fileType)  {
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
        String toDay = DateUtils.format(org.getToday(),"yyyyMMdd");

        String collectionFileName = fileType + "_" + toDay + "_" + fileName + ".del";

        String filePath = reportingPath + org.getTenantId() + File.separator + toDay + File.separator;

        Path reportingFile = Paths.get(filePath + collectionFileName);

        Integer i = 0;
        try(FileWriter bfw = new FileWriter(reportingFile.toFile(),true);
            BufferedWriter writer = new BufferedWriter(bfw,10240)) {
            if(reportingFile.toFile().length() != 0){
                writer.write("\r\n");
            }
            for (String message : messageList) {
                i++;
                if(i == messageList.size()){
                    writer.write(message);
                }else{
                    writer.write(message + "\r\n");
                }
            }
            writer.flush();
        } catch (IOException e) {
            logger.error("营销文件生成异常，异常信息：",e);
            throw new RuntimeException(e);
        }
    }

    //写入验签文件
    //furl：要存入文件路径 data1：数据文件路径
    @Override
    public boolean generatSignFile(PrOrganizationTable org, String marketFilePath, String marketFileName, String signFilePath) throws IOException {
        String toDay = DateUtils.format(org.getToday(),DateUtils.DATE_PATTERN_ANOTHER);
        File marketFile = new File(marketFilePath);
        Path reportingFile = Paths.get(signFilePath);

        try(FileWriter bfw = new FileWriter(reportingFile.toFile(),true);
            BufferedWriter writer = new BufferedWriter(bfw,10240)) {
            FileReader fileReader = new FileReader(marketFilePath);
            LineNumberReader LineNumberReader = new LineNumberReader(fileReader);
            LineNumberReader.skip(Long.MAX_VALUE);
            fileReader.close();
            long lines = LineNumberReader.getLineNumber();
            LineNumberReader.close();

            String wirt = toDay + " " + org.getTenantId() + " " + marketFileName + " " + marketFileName + " " + marketFile.getName() + " " + lines + " " + marketFile.length() + " " + "0 0 0 0";
            writer.write(wirt);
            writer.write("\r\n");
            writer.flush();
        } catch (IOException e) {
            logger.error("生成验签文件出错：" + e.getMessage());
            return false;
        }
        return true;
    }

    private void mergeReportingFile(String reportingPath, String toDay, String fileType, String tenantId)  {
        //获取目录下所有文件
        File file = new File(reportingPath);
        File[] tempList = file.listFiles();
        if(tempList == null || tempList.length == 0){
            logger.error("文件合并，未获取到需要合并的文件");
            throw new RuntimeException("文件合并，未获取到需要合并的文件");
        }

        List<File> mergeList = new ArrayList<>();

        for(int i = 0; i < tempList.length; i++){
            if(tempList[i].isFile()){
                String fileName = tempList[i].getName();
                String subStr = fileName.substring(0,fileType.length());
                if(fileType.equals(subStr)){
                    mergeList.add(tempList[i]);
                }
            }
        }
        //合并文件
        String resultFilePath = reportingPath + tenantId + "_" + fileType + "_" + "ADD" + "_" + toDay + ".del";
        File resultFile = new File(resultFilePath);

        Boolean isNullFile = true;
        try(FileChannel resultFileChannel= new FileOutputStream(resultFile, true).getChannel()){
            for(int i = 0; i < mergeList.size(); i++){
                FileChannel blk1 = new FileInputStream(mergeList.get(i)).getChannel();
                ByteBuffer buf = ByteBuffer.allocate(48);
                if(i == 0 && blk1.size() == 0){
                    resultFile.createNewFile();
                }else if (i < mergeList.size() && blk1.size() != 0){
                    if(!isNullFile && i != 0){
                        //换行
                        buf.clear();
                        buf.put("\r\n".getBytes());
                        buf.flip();
                        while(buf.hasRemaining()) {
                            resultFileChannel.write(buf);
                        }
                    }
                    //写入新文件
                    resultFileChannel.transferFrom(blk1, resultFileChannel.size(), blk1.size());
                    isNullFile = false;
                }
                blk1.close();
                //营销明细文件合并后在结尾写入一个换行符
                if(TransBizConstant.FILE_NAME_MARKET_DET.equals(fileType) && i == (mergeList.size() - 1)){
                    //结尾写入一个换行符
                    buf.clear();
                    buf.put("\r\n".getBytes());
                    buf.flip();
                    while(buf.hasRemaining()) {
                        resultFileChannel.write(buf);
                    }
                }
            }
        } catch (IOException e) {
            logger.error("文件合并异常，异常信息：",e);
            throw new RuntimeException(e);
        }
        //营销汇总文件合并后需合并同一推荐人相关数据
        if(TransBizConstant.FILE_NAME_MARKET_SUM.equals(fileType)){
            reGenerateSumFile(resultFilePath);
        }
    }

    //重新生成营销汇总文件，将同一推荐信息合并
    private void reGenerateSumFile(String resultFile) {
        File dirFile = new File(resultFile);
        if (dirFile.exists()) {
            InputStreamReader reader = null; // 建立一个输入流对象reader
            try {
                // 汇总信息读取
                reader = new InputStreamReader(new FileInputStream(resultFile), StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(reader);
                List<String[]> paramList = new ArrayList<>();
                String line = br.readLine();
                while (null != line){
                    line = line.replace("\"", "");
                    String params[] = line.split(",");
                    paramList.add((params));
                    line = br.readLine();
                }
                Map<String, Map<String,Object>> resMap = new HashMap<>();
                // 汇总信息重新计算
                for(String[] params1 : paramList){
                    String businessDate = params1[0];
                    String recommenderCode = params1[1];
                    Integer registCount = Integer.valueOf(params1[2]);
                    Integer creditCount = Integer.valueOf(params1[3]);
                    BigDecimal creditAmount =  new BigDecimal(params1[4]);
                    String tenantId = params1[10];
                    if (resMap.containsKey(recommenderCode)){
                        Map<String, Object> map = resMap.get(recommenderCode);
                        registCount = (Integer)map.get("registCount") + Integer.valueOf(params1[2]);
                        creditCount = (Integer)map.get("creditCount") + Integer.valueOf(params1[3]);
                        creditAmount =  ((BigDecimal)map.get("creditAmount")).add(new BigDecimal(params1[4]));
                        map.put("businessDate", businessDate);
                        map.put("recommenderCode", recommenderCode);
                        map.put("registCount", registCount);
                        map.put("creditCount", creditCount);
                        map.put("creditAmount", creditAmount);
                        map.put("tenantId", tenantId);
                    } else {
                        Map<String, Object> map = new HashMap<>();
                        map.put("businessDate", businessDate);
                        map.put("recommenderCode", recommenderCode);
                        map.put("registCount", registCount);
                        map.put("creditCount", creditCount);
                        map.put("creditAmount", creditAmount);
                        map.put("tenantId", tenantId);
                        resMap.put(recommenderCode, map);
                    }
                }

                // 组装写入信息
                List <String> messageList = new ArrayList<>();
                for(String key : resMap.keySet()){
                    Map<String, Object> res = resMap.get(key);
                    StringBuffer sb = new StringBuffer();
                    sb.append("\""+ res.get("businessDate") + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ res.get("recommenderCode") + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ res.get("registCount") + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ res.get("creditCount") + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ (res.get("creditAmount")==null?"0.00":((BigDecimal)res.get("creditAmount")).setScale(2, BigDecimal.ROUND_HALF_UP)) + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ "" + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ "" + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ "" + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ "" + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ "" + "\""+ TransBizConstant.SPLIT);
                    sb.append("\""+ res.get("tenantId")+ "\"");
                    messageList.add(sb.toString());
                }
                //写入文件
                Integer i = 0;
                try(FileWriter bfw = new FileWriter(dirFile, false);
                    BufferedWriter writer = new BufferedWriter(bfw,10240)) {
                    for (String message : messageList) {
                        i++;
                        if(i == messageList.size()){
                            writer.write(message);
                        }else{
                            writer.write(message + "\r\n");
                        }
                    }
                    //结尾写入一个换行符
                    writer.write("\r\n");
                    writer.flush();
                } catch (IOException e) {
                    logger.error("营销汇总文件重新写入异常，异常信息：",e);
                    throw new RuntimeException(e);
                }
            } catch (IOException e) {
                logger.error("读取营销汇总文件异常，异常信息：",e);
                throw new RuntimeException(e);
            }
        }
    }
}
